// Copyright 2006 PR1ME. All Rights Reserved.
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.util.ArrayList;
import java.util.List;

/**
 * Processes command-line arguments into logical options.
 */
public class ArgumentProcessor {

  /**
   * Process command-line arguments into logical options.
   * 
   * @param args a set of command-line arguments
   * @return a set of user settings
   * @throws IllegalArgumentException if the user arguments are malformed
   */
  public static UserSettings process(String[] args)
      throws IllegalArgumentException {

    // Initialize all option values to sentinal values
    String stopFileName = null;
    String variableBreakChars = null;

    /*
     * Try to process args as options.
     */
    int i = 0; // declare outside the loop to preserve value for second loop
    for (; i < args.length - 1; ++i) {
      String arg = args[i];
      // Check the option
      if ("-b".equals(arg) && variableBreakChars == null) {
        variableBreakChars = args[++i];
      } else if ("-s".equals(arg) && stopFileName == null) {
        stopFileName = args[++i];
      } else {
        // done with options
        break;
      }
    }

    // The remaining argument is treated as input file name.
    if (i < args.length - 1) {
      throw new IllegalArgumentException("too many arguments");
    } else if (i > args.length - 1) {
      throw new IllegalArgumentException("no indexing file was specified");
    }

    String indexFileName = args[i];
    List inputFileNames = new ArrayList();
    try {
      InputStream indexFile = FileStreamCreator.createInputStream(indexFileName);
      // A list to collect input file names
      processIndexFile(indexFile, inputFileNames);
      if (inputFileNames.size() == 0) {
        throw new IllegalArgumentException("no input files were specified");
      }

    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException("indexing file '" + indexFileName
          + "' does not exist");
    } catch (IOException e) {
      throw new IllegalArgumentException("indexing file '" + indexFileName
          + "' cannot be read from");
    }

    CharacterAnalyzer cAnalyzer = new CharacterAnalyzer();
    if (variableBreakChars != null) {
      cAnalyzer = new CharacterAnalyzer(variableBreakChars);
    }

    WordAnalyzer wordAnalyzer = new WordAnalyzer();
    if (stopFileName != null) {
      try {
        InputStream stopFileInputStream = FileStreamCreator.createInputStream(stopFileName);
        wordAnalyzer = new WordAnalyzer(cAnalyzer, stopFileInputStream);
        stopFileInputStream.close();
      } catch (FileNotFoundException e) {
        throw new IllegalArgumentException("stop file '" + stopFileName
            + "' does not exist");
      } catch (IOException e) {
        throw new IllegalArgumentException("stop file '" + stopFileName
            + "' cannot be read from");
      }
    }

    // Construct and return the logical user settings
    return new UserSettings(inputFileNames, cAnalyzer, wordAnalyzer,
        stopFileName);
  }

  private static void processIndexFile(InputStream indexFile,
      List inputFileNames) throws IOException {
    LineNumberReader in = new LineNumberReader(new InputStreamReader(indexFile));
    String line;
    while (null != (line = in.readLine())) {
      line = line.trim();
      if (line.length() > 0) {
        inputFileNames.add(line);
      }
    }
  }

  /**
   * Not instantiable.
   */
  private ArgumentProcessor() {
  }

}
